#include <os/list.h>
#include <os/mm.h>
#include <os/lock.h>
#include <os/sched.h>
#include <os/time.h>
#include <os/irq.h>
#include <screen.h>
#include <stdio.h>
#include <assert.h>

pcb_t pcb[NUM_MAX_TASK];
const ptr_t pid0_stack = INIT_KERNEL_STACK + PAGE_SIZE;
pcb_t pid0_pcb = {
    .pid = 0,
    .kernel_sp = (ptr_t)pid0_stack,
    .user_sp = (ptr_t)pid0_stack,
    .preempt_count = 0
};

LIST_HEAD(ready_queue);

/* current running task PCB */
pcb_t * volatile current_running;

/* global process id */
pid_t process_id = 1;

void do_scheduler(void)
{
    // TODO schedule
    // Modify the current_running pointer.

    // restore the current_runnint's cursor_x and cursor_y
    //timer_check();
    pcb_t *last_running;
    last_running=current_running;
    if(ready_queue.next!=&ready_queue){ 
    if(current_running->pid!=0){
        if(current_running->status==TASK_RUNNING)
        {current_running->status=TASK_READY;
        list_add_tail( &current_running->list, &ready_queue);}
        current_running=list_entry(ready_queue.next,pcb_t,list); 
    }
    else{
        current_running=pcb; 
    }


    list_del(&current_running->list);
    current_running->status=TASK_RUNNING;
    //screen_reflush();
    vt100_move_cursor(current_running->cursor_x,
                      current_running->cursor_y);
    screen_cursor_x = current_running->cursor_x;
    screen_cursor_y = current_running->cursor_y;
}
    switch_to(last_running,current_running);
    //ret_from_exception(current_running);
    // TODO: switch_to current_running
}
void user_do_scheduler(){
    invoke_syscall(1,0,0,0);
}
void do_sleep(uint32_t sleep_time)
{
    // TODO: sleep(seconds)
    // note: you can assume: 1 second = `timebase` ticks
    // 1. block the current_runningr放入睡眠队列，这一步在creat
    //timer函数里实现，因为队列内嵌在pcb的timer_p里
    // 2. create a timer which calls `do_unblock` when timeout
    // 3. reschedule because the current_running is blocked.
    timer_create(&do_unblock,&(current_running->list),sleep_time*time_base);//由于数据结构的问题，现在Pcb有两个队列属性，时钟队列
    //在此处是单独使用的。
    //timer_creat函数将current_running放入睡眠队列，且设置好了唤醒时间
    //和返回函数和参数，原则上将要进行do_block，直接将要做的功能挪了过来
    current_running->status=TASK_BLOCKED;
    do_scheduler();
}

void do_block(list_node_t *pcb_node, list_head *queue)
{
    // TODO: block the pcb task into the block queue
    list_entry(pcb_node,pcb_t,list)->status=TASK_BLOCKED;
    list_del(pcb_node);
    list_add_tail(pcb_node,queue);
    do_scheduler();
}

void do_unblock(list_node_t *pcb_node)//释放一个
{
    // TODO: unblock the `pcb` from the block queue
    list_del(pcb_node);
    list_add_tail(pcb_node,&ready_queue);
    list_entry(pcb_node,pcb_t,list)->status=TASK_READY;
}
void do_unblock_all(list_head pcb_node)//释放全部
{
    list_node_t *cur=pcb_node.next;  
    list_node_t *temp;
    while(cur!=&pcb_node){
            list_entry(cur,pcb_t,list)->status=TASK_READY;      
            temp=cur;
            cur=cur->next;
            list_del(temp);
            list_add_tail(temp,&ready_queue);
            }
}